package com.fiberhome.nas.feature.common.ext

import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.lazy.grid.LazyGridItemInfo
import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.hapticfeedback.HapticFeedback
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.round
import kotlin.math.absoluteValue

/**
 * Int类型ID的照片网格拖动处理函数
 */
@JvmName("photoGridDragHandlerInt")
fun Modifier.photoGridDragHandler(
    lazyGridState: LazyGridState,
    haptics: HapticFeedback,
    selectedIds: MutableState<Set<Int>>,
    onSelectionChanged: (List<Int>, Boolean) -> Unit = { _, _ -> },
    autoScrollSpeed: MutableState<Float>,
    autoScrollThreshold: Float,
) = photoGridDragHandlerInternal(
    lazyGridState = lazyGridState,
    haptics = haptics,
    selectedIds = selectedIds,
    onSelectionChanged = onSelectionChanged,
    autoScrollSpeed = autoScrollSpeed,
    autoScrollThreshold = autoScrollThreshold,
    keyExtractor = { it.key as? Int }
)

/**
 * Long类型ID的照片网格拖动处理函数
 */
@JvmName("photoGridDragHandlerLong")
fun Modifier.photoGridDragHandler(
    lazyGridState: LazyGridState,
    haptics: HapticFeedback,
    selectedIds: MutableState<Set<Long>>,
    onSelectionChanged: (List<Long>, Boolean) -> Unit = { _, _ -> },
    autoScrollSpeed: MutableState<Float>,
    autoScrollThreshold: Float,
) = photoGridDragHandlerInternal(
    lazyGridState = lazyGridState,
    haptics = haptics,
    selectedIds = selectedIds,
    onSelectionChanged = onSelectionChanged,
    autoScrollSpeed = autoScrollSpeed,
    autoScrollThreshold = autoScrollThreshold,
    keyExtractor = { it.key as? Long }
)

/**
 * String类型ID的照片网格拖动处理函数
 */
@JvmName("photoGridDragHandlerString")
fun Modifier.photoGridDragHandler(
    lazyGridState: LazyGridState,
    haptics: HapticFeedback,
    selectedIds: MutableState<Set<String>>,
    onSelectionChanged: (List<String>, Boolean) -> Unit = { _, _ -> },
    autoScrollSpeed: MutableState<Float>,
    autoScrollThreshold: Float,
) = photoGridDragHandlerInternal(
    lazyGridState = lazyGridState,
    haptics = haptics,
    selectedIds = selectedIds,
    onSelectionChanged = onSelectionChanged,
    autoScrollSpeed = autoScrollSpeed,
    autoScrollThreshold = autoScrollThreshold,
    keyExtractor = { it.key as? String }
)

fun <T> Modifier.photoGridDragHandlerInternal(
    lazyGridState: LazyGridState,
    haptics: HapticFeedback,
    selectedIds: MutableState<Set<T>>,
    onSelectionChanged: ((List<T>, Boolean) -> Unit)?,
    autoScrollSpeed: MutableState<Float>,
    autoScrollThreshold: Float,
    keyExtractor: (LazyGridItemInfo) -> T?
) = pointerInput(Unit) {
    var initialKey: T? = null
    var currentKey: T? = null
    var initialSelected = false
    var lastProcessedPosition: Offset? = null
    val positionThreshold = 5f // 位置变化阈值，减少不必要的计算

    // 缓存可见项的边界信息，加速查找
    data class ItemBounds(val key: T, val left: Int, val top: Int, val right: Int, val bottom: Int)

    var cachedItemBounds: List<ItemBounds> = emptyList()

    // 优化的网格项查找函数
    fun LazyGridState.gridItemKeyAtPositionOptimized(hitPoint: Offset): T? {
        val point = hitPoint.round()
        // 先检查缓存
        cachedItemBounds.forEach { bounds ->
            if (point.x in bounds.left..bounds.right && point.y in bounds.top..bounds.bottom) {
                return bounds.key
            }
        }
        // 缓存未命中时，重建缓存并查找
        val visibleItems = layoutInfo.visibleItemsInfo
        cachedItemBounds = visibleItems.mapNotNull { itemInfo ->
            keyExtractor(itemInfo)?.let {
                val offset = itemInfo.offset
                val size = itemInfo.size
                ItemBounds(
                    key = it,
                    left = offset.x,
                    top = offset.y,
                    right = (offset.x + size.width),
                    bottom = (offset.y + size.height)
                )
            }
        }
        return cachedItemBounds.find {
            point.x in it.left..it.right && point.y in it.top..it.bottom
        }?.key
    }

    // 处理直接拖动手势（无需长按）
    detectDragGestures(
        onDragStart = { offset ->
            lazyGridState.gridItemKeyAtPositionOptimized(offset)?.let { key ->
                initialKey = key
                currentKey = key
                haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove)
                initialSelected = selectedIds.value.contains(key)
                onSelectionChanged?.invoke(listOf(key), !initialSelected)
                // 初始化缓存
                cachedItemBounds = emptyList()
            }
        },
        onDragCancel = {
            initialKey = null
            autoScrollSpeed.value = 0f
            cachedItemBounds = emptyList()
        },
        onDragEnd = {
            initialKey = null
            autoScrollSpeed.value = 0f
            cachedItemBounds = emptyList()
        },
        onDrag = { change, _ ->
            if (initialKey != null) {
                // 位置变化小于阈值时不处理
                val currentPosition = change.position
                if (lastProcessedPosition?.let {
                        (currentPosition.x - it.x).absoluteValue < positionThreshold &&
                                (currentPosition.y - it.y).absoluteValue < positionThreshold
                    } != false) {
                    lastProcessedPosition = currentPosition
                    return@detectDragGestures
                }
                lastProcessedPosition = currentPosition

                // 计算自动滚动速度
                autoScrollSpeed.value = calculateAutoScrollSpeed(
                    lazyGridState.layoutInfo.viewportSize.height - currentPosition.y,
                    currentPosition.y,
                    autoScrollThreshold
                )

                // 处理选择变更
                lazyGridState.gridItemKeyAtPositionOptimized(currentPosition)?.let { newKey ->
                    if (currentKey != newKey) {
                        // 只在key变化时更新
                        currentKey = handleSelectionChange(
                            newKey = newKey,
                            lazyGridState = lazyGridState,
                            keyExtractor = keyExtractor,
                            selectedIds = selectedIds,
                            onSelectionChanged = onSelectionChanged,
                            initialKey = initialKey,
                            currentKey = currentKey,
                            initialSelected = initialSelected
                        )
                    }
                }
            }
        }
    )
}

/**
 * 计算自动滚动速度
 */
private fun calculateAutoScrollSpeed(
    distanceFromBottom: Float,
    distanceFromTop: Float,
    autoScrollThreshold: Float
): Float {
    return when {
        distanceFromBottom < autoScrollThreshold -> autoScrollThreshold - distanceFromBottom
        distanceFromTop < autoScrollThreshold -> -(autoScrollThreshold - distanceFromTop)
        else -> 0f
    }
}

/**
 * 通用选择处理逻辑
 */
private fun <T> handleSelectionChange(
    newKey: T,
    lazyGridState: LazyGridState,
    keyExtractor: (LazyGridItemInfo) -> T?,
    selectedIds: MutableState<Set<T>>,
    onSelectionChanged: ((List<T>, Boolean) -> Unit)?,
    initialKey: T?,
    currentKey: T?,
    initialSelected: Boolean
): T? {
    if (currentKey == newKey) return currentKey

    // 获取可见项并创建ID-索引映射
    val visibleItems = lazyGridState.layoutInfo.visibleItemsInfo
    val itemIndexMap = createItemIndexMap(visibleItems, keyExtractor)

    val allItemIds = itemIndexMap.keys.toList()

    // 通过映射表查找索引
    val startIndex = initialKey?.let { itemIndexMap[it] } ?: -1
    val currentIdx = currentKey?.let { itemIndexMap[it] } ?: -1
    val newIdx = itemIndexMap[newKey] ?: -1

    // 更新选择范围
    updateSelectionRange(
        allItemIds,
        startIndex,
        currentIdx,
        selectedIds,
        onSelectionChanged,
        initialSelected
    )
    updateSelectionRange(
        allItemIds,
        startIndex,
        newIdx,
        selectedIds,
        onSelectionChanged,
        !initialSelected
    )

    return newKey
}

/**
 * 更新选择范围的通用函数
 */
private fun <T> updateSelectionRange(
    allItemIds: List<T>,
    startIndex: Int,
    targetIndex: Int,
    selectedIds: MutableState<Set<T>>,
    onSelectionChanged: ((List<T>, Boolean) -> Unit)?,
    isAddOperation: Boolean
) {
    if (startIndex != -1 && targetIndex != -1) {
        val rangeIds = getRangeIds(allItemIds, startIndex, targetIndex)
        onSelectionChanged?.invoke(rangeIds, isAddOperation)
    }
}

/**
 * 提取范围ID列表的通用函数
 */
private fun <T> getRangeIds(allItemIds: List<T>, start: Int, end: Int): List<T> {
    return if (start <= end) {
        allItemIds.subList(start, end + 1)
    } else {
        allItemIds.subList(end, start + 1)
    }
}

/**
 * 创建可见项ID到索引的映射表（优化String类型查找性能）
 */
private fun <T> createItemIndexMap(
    visibleItems: List<LazyGridItemInfo>,
    keyExtractor: (LazyGridItemInfo) -> T?
): Map<T, Int> {
    return visibleItems
        .sortedBy { it.index }
        .mapNotNull { item -> keyExtractor(item) }
        .withIndex()
        .associate { (index, key) -> key to index }
}